package cn.virens.web.components.shiro.simple;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import cn.hutool.core.util.StrUtil;
import cn.virens.web.components.shiro.ShiroAuthInterface;
import cn.virens.web.components.shiro.ShiroRealmInterface;

/**
 * 用户身份识别/权限校验
 * 
 * @文件   :CustomAuthorizingRealm.java
 * @作者   :cn.loioi
 * @创建时间 :2016年10月13日 下午12:56:59
 */
public class SimpleAuthorizingRealm extends AuthorizingRealm implements ShiroRealmInterface {
	private Logger logger = LoggerFactory.getLogger(SimpleAuthorizingRealm.class);

	@Autowired
	@Qualifier(ShiroAuthInterface.NAME)
	private ShiroAuthInterface shiroAuthInterface;

	public SimpleAuthorizingRealm() {
		this(new HashedCredentialsMatcher("MD5"));
	}

	public SimpleAuthorizingRealm(CacheManager manager) {
		this(manager, null);
	}

	public SimpleAuthorizingRealm(CredentialsMatcher matcher) {
		this(null, matcher);
	}

	public SimpleAuthorizingRealm(CacheManager manager, CredentialsMatcher matcher) {
		super(manager, matcher);
	}

	@Override
	public void clearAuthorizationInfo(PrincipalCollection principals) {
		this.clearCachedAuthorizationInfo(principals);
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		logger.debug("执行授权信息...");
		String account = (String) getAvailablePrincipal(principals);
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

		authorizationInfo.addRoles(shiroAuthInterface.getRoles(account));// 获取用户角色列表
		authorizationInfo.addStringPermissions(shiroAuthInterface.getResources(account)); // 获取用户权限列表

		return authorizationInfo;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		logger.debug("执行身份验证信息...");

		// 获取用户信息
		String account = String.valueOf(token.getPrincipal());
		if (StrUtil.isEmpty(account)) { throw new UnknownAccountException("用户不存在"); }

		String password = shiroAuthInterface.login(account);
		if (StrUtil.isEmpty(password)) { throw new UnknownAccountException("用户不存在"); }

		return new SimpleAuthenticationInfo(account, password, getName());
	}

	@Override
	protected Object getAuthenticationCacheKey(AuthenticationToken token) {
		return token("shrio:authentication:", token);
	}

	@Override
	protected Object getAuthenticationCacheKey(PrincipalCollection principals) {
		return object("shrio:authentication:", super.getAvailablePrincipal(principals));
	}

	@Override
	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
		return object("shrio:authorization:", principals);
	}

	private String token(String pref, AuthenticationToken token) {
		return (token == null ? null : (pref + token.getPrincipal()));
	}

	private String object(String pref, Object obj) {
		return (obj == null ? null : (pref + obj.toString()));
	}
}
